module cache_group
#(parameter ID = 0)
(
	input clk,
	input [1:0] id,
	input [63:0] renew_data,
	input [4:0] tag,
	input offset,
	input write_enable,
	output hit,
	output [31:0] read_from_group,another_half,
	output reg if_changed,
	output reg [4:0] changed_tag,
	output reg [63:0] changed_data,

	input [7:0] pdu_addr,
	output pdu_hit,
	output [31:0] read_for_pdu
);
//缓存组，每个组有2行，替换采取最远使用策略
reg [4:0]tags[1:0];
reg [1:0]used;//recent use=0;
reg [1:0]vld;
reg [63:0]data[1:0];

wire hit0,hit1;
wire full,first_write_choose;
wire we;

assign full=vld[0]&vld[1];
assign first_write_choose=hit?hit1:~((~vld[0])|(full&used[0]));
	//if hit, choose hit; else choose 0 when 0 is empty or full&far_used;
assign hit0=(ID==id)&vld[0]&(tag==tags[0]);
assign hit1=(ID==id)&vld[1]&(tag==tags[1]);
assign hit=hit0|hit1;
assign we=(ID==id)&write_enable;

initial begin
	vld<=0;
	{used[0],used[1]}<=0;
	if_changed<=0;
	changed_tag<=0;
	changed_data<=0;
end

//进行写操作
always @(posedge clk) begin

	//换出行，要求写且未中
	if(full&we&(~hit))begin
		if_changed<=1;
		changed_tag<=tags[first_write_choose];
		changed_data<=data[first_write_choose];
	end
	else begin//这个周期不需要换出行
		if_changed<=0;
		changed_tag<=0;
		changed_data<=0;
	end

	if(we)begin//换入行
		vld[first_write_choose]<=1;
		tags[first_write_choose]<=tag;
		data[first_write_choose]<=renew_data;
	end
	
end

//调整命中顺序
always@(*)begin
	if(hit0)begin
		used[0]=0;
		used[1]=vld[1];
	end
	else if(hit1)begin
		used[1]=0;
		used[0]=vld[0];
	end
end

//读操作
assign read_from_group=
	hit?(
		offset?data[hit1][63:32]:data[hit1][31:0]
	):0;
assign another_half=
	hit?(
		offset?data[hit1][31:0]:data[hit1][63:32]
	):0;

//for pdu
wire pdu_hit1,pdu_hit2;
assign pdu_hit0=(ID==pdu_addr[2:1])&(pdu_addr[7:3]==tags[0]);
assign pdu_hit1=(ID==pdu_addr[2:1])&(pdu_addr[7:3]==tags[1]);
assign pdu_hit=pdu_hit0&pdu_hit1;
assign read_for_pdu=
	pdu_hit?(
		offset?data[pdu_hit1][63:32]:data[pdu_hit1][31:0]
	):0;

endmodule